package com.ztesoft.book.api.controller.wx;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ztesoft.book.common.constant.CommonParamUtil;
import com.ztesoft.book.common.utils.Result;
import com.ztesoft.book.core.wx.pay.service.WechatPayService;
import com.ztesoft.book.core.wx.pay.vo.PreOkVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Description 微信接口
 * @Author YangFan
 * @Date 2021-07-16 13:50
 */
@Slf4j
@RestController
@RequestMapping("/wxpay")
public class WechatPayController {

    @Value("${book.weixin.xcx-appid}")
    private String XCX_APPID;
    @Value("${book.pay.mchid}")
    private String merchantId;
    @Value("${book.pay.notifyPay}")
    private String notifyPay;
    @Value("${book.pay.notifyRefund}")
    private String notifyRefund;

    @Resource
    private WechatPayService wechatPayService;


    /**
     * 方法功能描述:
     * < 预支付生成 + 更新订单信息 >
     *
     * @param vo 参数说明
     * @return Result
     * @author YangFan
     * @date 2021-07-29 17:58
     */
    @PostMapping("/getPrepayIdAndUpdateOrder")
    public Result getPrepayIdAndUpdateOrder(@RequestBody PreOkVO vo) {
        // 根据接口传参修改订单数据（重复修改没有影响）（参数检查）
        if (StringUtils.isBlank(vo.getOrderId())) {
            return Result.error("订单单号不能为空");
        }
        if (StringUtils.isBlank(vo.getOpenId())) {
            return Result.error("小程序OpenId不能为空");
        }

        try {
            // TODO: 2021-08-29 这里增加订单状态更新的方法
        }
        catch (Exception e) {
            return Result.error("订单更新失败：" + e.getMessage());
        }

        Integer orderTotal = CommonParamUtil.INT_0;
        String prepayId = "";
        JSONObject object = null;
        // TODO: 2021-08-29 验证订单金额是否大于0
        if (orderTotal > 0) {
            try {
                // TODO: 2021-08-29 这里可以增加一些订单校验 

                // 根据接口传参封装参数
                ObjectMapper objectMapper = new ObjectMapper();
                ObjectNode rootNode = objectMapper.createObjectNode();
                rootNode.put("mchid", merchantId)
                        .put("appid", XCX_APPID)
                        .put("description", "在线书城订单")
                        .put("notify_url", notifyPay)
                        .put("out_trade_no", "支付单号");
                rootNode.putObject("amount")
                        .put("total", orderTotal);
                rootNode.putObject("payer")
                        .put("openid", vo.getOpenId());
                prepayId = wechatPayService.createPrepay(rootNode);
                if (StringUtils.isBlank(prepayId)) {
                    return Result.error("微信预支付订单生成失败");
                }
                object = wechatPayService.wxTuneUp(prepayId, XCX_APPID);
                object.put("needWxPay", 1);
            }
            catch (Exception e) {
                return Result.error(e.getMessage());
            }
            return Result.successNoMap(object);
        }
        else {
            // 付款金额为0的时候，直接进入订单成功处理逻辑
            Map<String, Object> res = new HashMap<>(16);
            res.put("needWxPay", 0);
            res.put("msg", "支付金额为0，无需微信支付");

            // TODO: 2021-08-29  这里增加订单支付成功逻辑（因为支付金额为0，所以无需等待回调，直接成功）

            return Result.successNoMap(res);
        }

    }


    /**
     * 方法功能描述:
     * < 支付成功回调 >
     *
     * @param request  参数说明
     * @param response 参数说明
     * @return void
     * @author YangFan
     * @date 2021-07-29 17:58
     */
    @RequestMapping(value = "/notifyPay", method = {org.springframework.web.bind.annotation.RequestMethod.POST, org.springframework.web.bind.annotation.RequestMethod.GET})
    public void notifyPay1(HttpServletRequest request, HttpServletResponse response) {
        log.info("支付成功回调");
        JSONObject jsonObject = null;
        try {
            jsonObject = wechatPayService.notify(request, response);
        }
        catch (Exception e) {
            log.error("【notifyPay异常】：" + e.getMessage());
        }

        if (jsonObject != null) {
            String out_trade_no = jsonObject.getString("out_trade_no");
            log.info("----------订单支付成功回调：【{}】", out_trade_no);

            // 单号可能是带_符号的，需要处理
            String[] trueNo = out_trade_no.split("_");
            // TODO: 2021-08-29  这里增加支付成功处理订单逻辑
        }
    }


    /**
     * 方法功能描述:
     * < 退款申请接口 >
     *
     * @param vo 参数说明
     * @return Result
     * @author YangFan
     * @date 2021-07-30 16:03
     */
    @PostMapping("/createRefund")
    public Result createRefund(@RequestBody PreOkVO vo) {
        // 测试用，无入参校验，仅两个参数：orderId（订单id - String），amount（退款金额 - Integer）

        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        // TODO: 2021-08-29 这里查找退款订单 
        
        JSONObject object = null;
        Integer rightsState = CommonParamUtil.INT_3;
        Integer orderTotal = CommonParamUtil.INT_0;
        
        // TODO: 2021-08-29 这里对订单状态进行判断 
        if (rightsState.equals(CommonParamUtil.INT_3)) {
            // TODO: 2021-08-29 判断可退款金额是否为0 
            if (orderTotal > 0) {
                // 仅退款审核状态的订单可调用接口，并更新为退款中
                // TODO: 2021-08-29 这里修改订单状态位退款中 

                // 根据接口传参封装参数
                ObjectMapper objectMapper = new ObjectMapper();
                ObjectNode rootNode = objectMapper.createObjectNode();
                rootNode.put("notify_url", notifyRefund)
                        .put("out_trade_no", "订单支付单号")
                        .put("out_refund_no", "订单ID" + "|" + nonceStr);
                rootNode.putObject("amount")
                        .put("refund", vo.getAmount())
                        .put("total", orderTotal)
                        .put("currency", "CNY");
                try {
                    object = wechatPayService.createRefund(rootNode);
                }
                catch (Exception e) {
                    return Result.error(e.getMessage());
                }
            }
            else {
                return Result.error("订单实际支付金额为0,不可以申请退款");
            }
        }
        else {
            return Result.error("仅退款审核状态的订单可调用接口");
        }
        return Result.successNoMap(object);
    }


    /**
     * 方法功能描述:
     * < 退款成功回调 >
     *
     * @param request  参数说明
     * @param response 参数说明
     * @return void
     * @author YangFan
     * @date 2021-07-30 16:11
     */
    @RequestMapping(value = "/notifyRefund", method = {org.springframework.web.bind.annotation.RequestMethod.POST, org.springframework.web.bind.annotation.RequestMethod.GET})
    public void notifyRefund1(HttpServletRequest request, HttpServletResponse response) {
        log.info("退款成功回调");
        JSONObject jsonObject = null;
        try {
            jsonObject = wechatPayService.notify(request, response);
        }
        catch (Exception e) {
            log.error("【notifyRefund异常】：" + e.getMessage());
        }

        if (jsonObject != null) {
            String out_trade_no = jsonObject.getString("out_trade_no");
            log.info("----------订单退款成功回调：【{}】", out_trade_no);

            // 单号可能是带_符号的，需要处理
            String[] trueNo = out_trade_no.split("_");
            // TODO: 2021-08-29 订单退款成功回调
        }
    }


}



